﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Drawing;

namespace UnrealConverterLogic
{
    public partial class UnrealConverter
    {
        private struct Conversions
        {
            public string SetName { get; set; }
            public double UnrealUnits { get; set; }
            public double MaxUnits { get; set; }
            public double Meters { get; set; }

            public string[] ToStringArray()
            {
                return
                    new string[]
                    {
                        SetName,
                        UnrealUnits.ToString(),
                        MaxUnits.ToString(),
                        Meters.ToString()
                    };
            }
        }
        private static Conversions CurrentConversion;
        private static string[] strInputFields;
        private static bool bFocusOverride = false;
        public static void InitializeMainInputs()
        {
            tbInputSetName.Text = CurrentConversion.SetName;
            bFocusOverride = true;
            tbInputUU.Text = CurrentConversion.UnrealUnits.ToString();
            UpdateLabelColors(InputField.UNREAL);
        }

        public static void SwitchMainInputsToConversion(object sender, EventArgs e)
        {
            rbConversion.TabStop = false;
            rbRatios.TabStop = false;
            if (rbConversion.Checked)
            {
                StopListeningForRatioChanges();
                SetInputsToConversion();
                SetListenersForConversion();
            }
        }
        public static void StopListeningForRatioChanges()
        {
            bEditingRatios = false;
            tbInputSetName.TextChanged -= UnrealConverter.OnRatioFieldChangedEventHandler;
            tbInputSetName.KeyDown -= UnrealConverter.OnRatioFieldEnterPressed;

            tbInputUU.TextChanged -= UnrealConverter.OnRatioFieldChangedEventHandler;
            tbInputUU.KeyDown -= UnrealConverter.OnRatioFieldEnterPressed;

            tbInputMaxUnits.TextChanged -= UnrealConverter.OnRatioFieldChangedEventHandler;
            tbInputMaxUnits.KeyDown -= UnrealConverter.OnRatioFieldEnterPressed;

            tbInputMeters.TextChanged -= UnrealConverter.OnRatioFieldChangedEventHandler;
            tbInputMeters.KeyDown -= UnrealConverter.OnRatioFieldEnterPressed;
        }
        public static void SetListenersForConversion()
        {
            bConverting = true; 
            tbInputUU.LostFocus += UnrealConverter.OnMathFieldFocusLost;
            tbInputUU.GotFocus += UnrealConverter.OnMathFieldFocusGained;

            tbInputMaxUnits.LostFocus += UnrealConverter.OnMathFieldFocusLost;
            tbInputMaxUnits.GotFocus += UnrealConverter.OnMathFieldFocusGained;

            tbInputMeters.LostFocus += UnrealConverter.OnMathFieldFocusLost;
            tbInputMeters.GotFocus += UnrealConverter.OnMathFieldFocusGained;

            tbInputSetName.TextChanged += UnrealConverter.OnMathFieldChangedEventHandler;
            tbInputSetName.KeyDown += UnrealConverter.OnInputSetNameKeyPress;

            tbInputUU.TextChanged += UnrealConverter.OnMathFieldChangedEventHandler;
            tbInputUU.KeyDown += UnrealConverter.OnInputSetNameKeyPress;

            tbInputMaxUnits.TextChanged += UnrealConverter.OnMathFieldChangedEventHandler;
            tbInputMaxUnits.KeyDown += UnrealConverter.OnInputSetNameKeyPress;

            tbInputMeters.TextChanged += UnrealConverter.OnMathFieldChangedEventHandler;
            tbInputMeters.KeyDown += UnrealConverter.OnInputSetNameKeyPress;
        }
        public static void SetInputsToConversion()
        {
            bEditingRatios = false;
            tbInputSetName.Text     = CurrentConversion.SetName;
            tbInputUU.Text          = CurrentConversion.UnrealUnits.ToString();
            tbInputMaxUnits.Text    = CurrentConversion.MaxUnits.ToString();
            tbInputMeters.Text      = CurrentConversion.Meters.ToString();
        }
        public static void OnInputSetNameKeyPress(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Return && !areInputsEmpty())
            {
                if (dgvReferences != null) AddCurrentSetToReference(sender, e);
                else AddCurrentSetToReference(sender, e);
                tbInputUU.Text = "";
                tbInputMaxUnits.Text = "";
                tbInputMeters.Text = "";
                tbInputSetName.Text = "";
            }
        }
        private static bool areInputsEmpty()
        {
            return
                (
                    tbInputUU.Text == "" ||
                    tbInputMaxUnits.Text == "" ||
                    tbInputMeters.Text == ""
                );
        }
        private static bool InputFieldsNotEmpty()
        {
            return tbInputUU.Text != "" &&
                    tbInputMaxUnits.Text != "" &&
                    tbInputMeters.Text != "";
        }
        public static void CatchHotKeys(object sender, KeyEventArgs e)
        {
            TextBox tb = ((TextBox)sender);
            if (e.Control && e.KeyCode.ToString() == "A")
            {
                tb.SelectAll();
            }
            if (e.Control && e.KeyCode.ToString() == "X")
            {
                tb.Cut();
            }
            if (e.Control && e.KeyCode.ToString() == "C")
            {
                tb.Copy();
            }
            if (e.Control && e.KeyCode.ToString() == "V")
            {
                object clipboardObject = Clipboard.GetText();
                if (clipboardObject.GetType() == typeof(string) ||
                    clipboardObject.GetType() == typeof(int) ||
                    clipboardObject.GetType() == typeof(double) ||
                    clipboardObject.GetType() == typeof(float))
                {
                    double number;
                    if (Double.TryParse(clipboardObject.ToString(), out number) &&
                        !tb.Name.Contains("SetName"))
                    {
                        tb.Paste(number.ToString());
                    }
                    else
                    {
                        tb.Paste(clipboardObject.ToString());
                    }
                }
            }
        }
        public static void Validate(object sender, KeyPressEventArgs e)
        {
            e.Handled =
                !(e.KeyChar == 41 || e.KeyChar == 40 ||
                (e.KeyChar > 47 && e.KeyChar < 58) ||
                e.KeyChar == 8 ||
                e.KeyChar == 45 ||
                e.KeyChar == 43 ||
                e.KeyChar == 42 ||
                e.KeyChar == 47 ||
                e.KeyChar == 46);
        }
        public static void OnMathFieldFocusLost(object sender, EventArgs e)
        {
                if (((TextBox)sender).Name == "tbInputUU")
                {
                    LastFocusedInputField = InputField.UNREAL;
                    UpdateLabelColors(LastFocusedInputField);
                }
                if (((TextBox)sender).Name == "tbInputMaxUnits")
                {
                    LastFocusedInputField = InputField.MAX;
                    UpdateLabelColors(LastFocusedInputField);
                }
                if (((TextBox)sender).Name == "tbInputMeters")
                {
                    LastFocusedInputField = InputField.METERS;
                    UpdateLabelColors(LastFocusedInputField);
                }
        }
        public static bool NotEmptyAndIsDouble(TextBox tb)
        {
            double dummy;
            if (tb.Text == "") return false;
            else return isValidDouble(tb, out dummy);
        }
        public static void OnMathFieldFocusGained(object sender, EventArgs e)
        {
            if (((TextBox)sender).Name == "tbInputUU")
            {
                LastFocusedInputField = InputField.UNREAL;
                UpdateLabelColors(LastFocusedInputField);
            }
            if (((TextBox)sender).Name == "tbInputMaxUnits")
            {
                LastFocusedInputField = InputField.MAX;
                UpdateLabelColors(LastFocusedInputField);
            }
            if (((TextBox)sender).Name == "tbInputMeters")
            {
                LastFocusedInputField = InputField.METERS;
                UpdateLabelColors(LastFocusedInputField);
            }
        }
        private static void UpdateLabelColors(InputField field)
        {
            switch (field)
            {
                case InputField.UNREAL:
                    gBMaxUnits.ForeColor = Color.Black;
                    tbInputMaxUnits.ForeColor = Color.Black;

                    gBMeters.ForeColor = Color.Black;
                    tbInputMeters.ForeColor = Color.Black;

                    gBUU.ForeColor = Color.SteelBlue;
                    tbInputUU.ForeColor = Color.SteelBlue;
                    break;
                case InputField.METERS:
                    gBMaxUnits.ForeColor = Color.Black;
                    tbInputMaxUnits.ForeColor = Color.Black;

                    gBMeters.ForeColor = Color.SteelBlue;
                    tbInputMeters.ForeColor = Color.SteelBlue;

                    gBUU.ForeColor = Color.Black;
                    tbInputUU.ForeColor = Color.Black;
                    break;
                case InputField.MAX:
                    gBMaxUnits.ForeColor = Color.SteelBlue;
                    tbInputMaxUnits.ForeColor = Color.SteelBlue;

                    gBMeters.ForeColor = Color.Black;
                    tbInputMeters.ForeColor = Color.Black;

                    gBUU.ForeColor = Color.Black;
                    tbInputUU.ForeColor = Color.Black;
                    break;
            } 
        }
        public static void OnMathFieldChangedEventHandler(object sender, EventArgs e)
        {
            if (((TextBox)sender).Name == "tbInputSetName")
            {
                CurrentConversion.SetName = tbInputSetName.Text;
            }
            if (((TextBox)sender).Focused || bFocusOverride)
            {
                bFocusOverride = false;
                if (((TextBox)sender).Name == "tbInputUU")
                {
                    LastFocusedInputField = InputField.UNREAL;
                    #region TextBox is empty
                    if (((TextBox)sender).Text == "")
                    {
                        tbInputMaxUnits.Text = "";
                        tbInputMeters.Text = "";
                    }
                    #endregion
                    else
                    {
                        UpdateMathFields(Units.UNREAL_UNITS);
                        tbInputUU.Select(tbInputUU.Text.Length, 0);
                    }
                    if (isValidDouble(((TextBox)sender), out fUnrealUnits)) CurrentConversion.UnrealUnits = Double.Parse(tbInputUU.Text);
                }
                if (((TextBox)sender).Name == "tbInputMaxUnits")
                {
                    LastFocusedInputField = InputField.MAX;
                    #region TextBox is empty
                    if (((TextBox)sender).Text == "")
                    {
                        tbInputMeters.Text = "";
                        tbInputUU.Text = "";
                    }
                    #endregion
                    else
                    {
                        UpdateMathFields(Units.MAX_UNITS);
                        tbInputMaxUnits.Select(tbInputMaxUnits.Text.Length, 0);
                    }
                    if (isValidDouble(((TextBox)sender), out fMaxUnits)) CurrentConversion.MaxUnits = Double.Parse(tbInputMaxUnits.Text);
                }
                if (((TextBox)sender).Name == "tbInputMeters")
                {
                    LastFocusedInputField = InputField.METERS;
                    #region TextBox is empty
                    if (((TextBox)sender).Text == "")
                    {
                        tbInputMaxUnits.Text = "";
                    }
                    #endregion
                    else
                    {
                        UpdateMathFields(Units.METERS);
                        tbInputMeters.Select(tbInputMeters.Text.Length, 0);
                    }
                    if (isValidDouble(((TextBox)sender), out fMeters)) CurrentConversion.Meters = Double.Parse(tbInputMeters.Text);
                }
            }
                /*
            else
            {
                if (((TextBox)sender).Name == "tbInputUU")
                {
                    if (isValidDouble(((TextBox)sender), out fUnrealUnits))
                    {
                        CurrentConversion.UnrealUnits = Double.Parse(tbInputUU.Text);
                    }
                }
                if (((TextBox)sender).Name == "tbInputMaxUnits")
                {
                    if (isValidDouble(((TextBox)sender), out fMaxUnits))
                    {
                        CurrentConversion.MaxUnits = Double.Parse(tbInputMaxUnits.Text);
                    }
                }
                if (((TextBox)sender).Name == "tbInputMeters")
                {
                    if(isValidDouble(((TextBox)sender), out fMeters))
                    {
                        CurrentConversion.Meters = Double.Parse(tbInputMeters.Text);
                    }
                }
            }
                 */
            UpdateGridArrays();
        }
        public static void UpdateMathFields(Units From)
        {
            switch (From)
            {
                case Units.UNREAL_UNITS:
                    if (isValidDouble(tbInputUU, out fUnrealUnits))
                    {
                        CurrentConversion.MaxUnits  = fUnrealUnits * fUUtoMax;
                        CurrentConversion.Meters    = fUnrealUnits * fUUtoMeters;

                        tbInputMaxUnits.Text    = CurrentConversion.MaxUnits.ToString();
                        tbInputMeters.Text      = CurrentConversion.Meters.ToString();
                    }
                    if (isValidMathExpression(tbInputUU, ref fUnrealUnits))
                    {
                        CurrentConversion.UnrealUnits   = fUnrealUnits;
                        CurrentConversion.MaxUnits      = fUnrealUnits * fUUtoMax;
                        CurrentConversion.Meters        = fUnrealUnits * fUUtoMeters;

                        tbInputUU.Text          = CurrentConversion.UnrealUnits.ToString();
                        tbInputMaxUnits.Text    = CurrentConversion.MaxUnits.ToString();
                        tbInputMeters.Text      = CurrentConversion.Meters.ToString();
                    }
                    else
                    {
                        tbInputMaxUnits.Text = "";
                        tbInputMeters.Text = "";
                    }
                    break;
                case Units.MAX_UNITS:
                    if (isValidDouble(tbInputMaxUnits, out fMaxUnits))
                    {
                        CurrentConversion.UnrealUnits   = fMaxUnits * fMaxtoUU;
                        CurrentConversion.Meters        = fMaxUnits * fMaxtoMeters;

                        tbInputUU.Text      = CurrentConversion.UnrealUnits.ToString();
                        tbInputMeters.Text  = CurrentConversion.Meters.ToString();
                    }
                    if (isValidMathExpression(tbInputMaxUnits, ref fMaxUnits))
                    {
                        CurrentConversion.MaxUnits      = fMaxUnits;
                        CurrentConversion.UnrealUnits   = fMaxUnits * fMaxtoUU;
                        CurrentConversion.Meters        = fMaxUnits * fMaxtoMeters;

                        tbInputMaxUnits.Text    = CurrentConversion.MaxUnits.ToString();
                        tbInputUU.Text          = CurrentConversion.UnrealUnits.ToString();
                        tbInputMeters.Text      = CurrentConversion.Meters.ToString();
                    }
                    else
                    {
                        tbInputUU.Text = "";
                        tbInputMeters.Text = "";
                    }
                    break;
                case Units.METERS:
                    if (isValidDouble(tbInputMeters, out fMeters))
                    {
                        CurrentConversion.UnrealUnits   = fMeters * fMeterstoUU;
                        CurrentConversion.MaxUnits      = fMeters * fMeterstoMax;

                        tbInputUU.Text          = CurrentConversion.UnrealUnits.ToString();
                        tbInputMaxUnits.Text    = CurrentConversion.MaxUnits.ToString();
                    }
                    if (isValidMathExpression(tbInputMeters, ref fMeters))
                    {
                        CurrentConversion.Meters        = fMeters;
                        CurrentConversion.UnrealUnits   = fMeters * fMeterstoUU;
                        CurrentConversion.MaxUnits      = fMeters * fMeterstoMax;

                        tbInputMeters.Text      = CurrentConversion.Meters.ToString();
                        tbInputUU.Text          = CurrentConversion.UnrealUnits.ToString();
                        tbInputMaxUnits.Text    = CurrentConversion.MaxUnits.ToString();
                    }
                    else
                    {
                        tbInputUU.Text = "";
                        tbInputMaxUnits.Text = "";
                    }
                    break;
            }
        }
    }
}
